package com.yycx.autoconfigure;

import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.AsyncTaskExecutor;
import org.springframework.core.task.TaskDecorator;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;

import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * 异步监听配置
 *
 * @author zyf
 */
@Configuration
@EnableAsync
public class ListenerAsyncConfiguration implements AsyncConfigurer {
    public static final String TASK_EXECUTOR_NAME = "taskExecutor";
    /**
     * 获取异步线程池执行对象
     *
     * @return
     */
    @Override
    @Bean(TASK_EXECUTOR_NAME)
    public AsyncTaskExecutor getAsyncExecutor() {
        //使用Spring内置线程池任务对象
        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
        //核心线程数（默认线程数）
        taskExecutor.setCorePoolSize(10);
        // 最大线程数
        taskExecutor.setMaxPoolSize(20);
        //缓冲队列数
        taskExecutor.setQueueCapacity(200);
        // 允许线程空闲时间（单位：默认为秒）
        taskExecutor.setKeepAliveSeconds(60);
        // 线程池名前缀
        taskExecutor.setThreadNamePrefix("flyme-asyncExecutor-");
        // 设置是否等待计划任务在关闭时完成
        taskExecutor.setWaitForTasksToCompleteOnShutdown(true);
        // 设置此执行器应该阻止的最大秒数
        taskExecutor.setAwaitTerminationSeconds(60);
        // 增加 TaskDecorator 属性的配置
        taskExecutor.setTaskDecorator(new ContextDecorator());
        // 线程池对拒绝任务的处理策略
        taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        taskExecutor.initialize();
        return taskExecutor;
    }

    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return null;
    }
    /**
     * 任务装饰器
     */
    class ContextDecorator implements TaskDecorator {
        @Override
        public Runnable decorate(Runnable runnable) {
            RequestAttributes context = RequestContextHolder.currentRequestAttributes();
            return () -> {
                try {
                    // 传递上下文
                    RequestContextHolder.setRequestAttributes(context);
                    runnable.run();
                } finally {
                    RequestContextHolder.resetRequestAttributes();
                }
            };
        }
    }
}
